All files / frontend/server/api/products/[gtin] manufacturing-distance.get.ts

0% Statements 0/62
0% Branches 0/1
0% Functions 0/1
0% Lines 0/62

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63                                                                                                                             
import {
  createError,
  defineEventHandler,
  getRequestIP,
  getRouterParam,
  setResponseHeader,
} from 'h3'

import { resolveDomainLanguage } from '~~/shared/utils/domain-language'

import { extractBackendErrorDetails } from '../../../utils/log-backend-error'

/**
 * Per-user user→manufacturing distance. NOT cacheable. This is the ONLY route
 * that forwards the real client IP to the backend (via X-Forwarded-For), so the
 * backend GeoIP can resolve the user's location for the distance computation.
 */
export default defineEventHandler(async event => {
  setResponseHeader(event, 'Cache-Control', 'no-store')

  const gtinParam = getRouterParam(event, 'gtin')
  if (!gtinParam) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Product GTIN is required',
    })
  }
  const parsedGtin = Number.parseInt(gtinParam, 10)
  if (!Number.isFinite(parsedGtin)) {
    throw createError({
      statusCode: 400,
      statusMessage: 'Product GTIN must be numeric',
    })
  }

  const rawHost =
    event.node.req.headers['x-forwarded-host'] ?? event.node.req.headers.host
  const { domainLanguage } = resolveDomainLanguage(rawHost)

  const clientIp = getRequestIP(event, { xForwardedFor: true }) ?? ''

  const { apiUrl, machineToken } = useRuntimeConfig(event)

  try {
    return await $fetch(`${apiUrl}/brands/distance/${parsedGtin}`, {
      headers: {
        'X-Shared-Token': machineToken as string,
        ...(clientIp
          ? { 'X-Forwarded-For': clientIp, 'X-Real-Ip': clientIp }
          : {}),
      },
      query: { domainLanguage },
    })
  } catch (error) {
    const backendError = await extractBackendErrorDetails(error)
    throw createError({
      statusCode: backendError.statusCode,
      statusMessage: backendError.statusMessage,
      cause: error,
    })
  }
})